#ifndef __GEEK_COMMANDER_LIST_H_INCLUDED_AA38FD09_33A6_4628_90FE_150E05E96087__
#define __GEEK_COMMANDER_LIST_H_INCLUDED_AA38FD09_33A6_4628_90FE_150E05E96087__

template<typename T>
struct geek_listnode
{
    T *prev;
    T *next;
};

template<typename T, geek_listnode<T> T::*O>
struct geek_list
{
    typedef T item_t;

    item_t *first;
    item_t *last;
    int item_count;

    static geek_listnode<T> *get_listnode(item_t *item)
    {
        return &(item->*O);
    }
};

template<typename L>
void geek_list_create(L *list)
{
    memset(list,0,sizeof(L));
}

template<typename L>
void geek_list_destroy(L *list)
{
    memset(list,0,sizeof(L));
}

template<typename L>
void geek_list_insert(L *list, typename L::item_t *before, typename L::item_t *item)
{
    typedef geek_listnode<typename L::item_t> node_t;
    node_t *node = L::get_listnode(item);
    node->next = before;

    if(before == NULL)
    {
        node->prev = list->last;

        if(list->last)
        {
            node_t *lastnode = L::get_listnode(list->last);
            lastnode->next = item;
        }
        else
        {
            list->first = item;
        }

        list->last = item;
    }
    else
    {
        node_t *beforenode = L::get_listnode(before);

        node->prev = beforenode->prev;
        if(beforenode->prev != NULL)
        {
            node_t *prevnode = L::get_listnode(beforenode->prev);
            prevnode->next = item;
        }

        beforenode->prev = item;

        if(before == list->first)
        {
            list->first = item;
        }
    }
}

template<typename L>
void geek_list_remove(L *list, typename L::item_t *item)
{
    typedef geek_listnode<typename L::item_t> node_t;
    node_t *node = L::get_listnode(item);

    if(node->next != NULL)
    {
        node_t *nextnode = L::get_listnode(node->next);
        nextnode->prev = node->prev;
    }
    else
    {
        list->last = node->prev;
    }

    if(node->prev != NULL)
    {
        node_t *prevnode = L::get_listnode(node->prev);
        prevnode->next = node->next;
    }
    else
    {
        list->first = node->next;
    }
}

#define GEEK_LIST_FOREACH(l,t,v)  \
    for(t *v = (l)->first; v != NULL; v = (l)->get_listnode(v)->next)

#endif // __GEEK_COMMANDER_LIST_H_INCLUDED_AA38FD09_33A6_4628_90FE_150E05E96087__
